
module frv_rob_entry (
    input                       clk                 ,
    input                       rst_n               ,
    input                       pd_rst              ,
    // Regfile Operation
    input                       rob_entry_wreq      ,
    input                       rob_entry_wrd_vld   ,
    input [4:0]                 rob_entry_wrd_ind   ,
    input                       rob_entry_wt_store  , //is Store?
    input                       rob_entry_exp_req   ,
    input [5:0]     rob_entry_winst_id  , // rob_entry_winst_id can be optimise to 1bit width !!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
    // Retire Interface
    input                       rob_entry_ret_req   ,//retire request
    output                      rob_entry_ready     ,   
    output                      rob_entry_vld       ,
    output                      rob_entry_bflush    ,
    output                      rob_entry_eflush    ,
    output                      rob_entry_store     ,
    output [4:0]                rob_entry_ecode     ,
    output                      rob_entry_rd_vld    ,
    output [4:0]                rob_entry_rd_ind    ,
    output [31:0]               rob_entry_val       ,
    output [5:0]    rob_entry_inst_id   , // rob_entry_winst_id can be optimise to 1bit width !!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
    //Flush
    // input                       rob_entry_flush     ,
    // FU Interface
    input                       alu_resp_vld        ,
    input [5:0]     alu_resp_inst_id    ,        
    input [31:0]                alu_resp_rd_val     ,    
    input                       bru_resp_vld        ,
    input [5:0]     bru_resp_inst_id    ,
    input                       bru_resp_rd_vld     ,
    input [31:0]                bru_resp_rd_val     ,
    input                       bru_flush           ,
    input                       lsu_resp_vld        ,
    input [5:0]     lsu_resp_inst_id    ,
    input                       lsu_resp_rd_vld     ,
    input [31:0]                lsu_resp_rd_val     , //rd value      
    input                       lsu_flush                
    
);

wire            entry_val_wen;
wire            entry_vld_wen;
wire            entry_branch_wen;
wire            entry_store_wen;
wire            entry_rd_vld_wen;
wire            entry_inst_id_wen;
wire            entry_exp_tag_wen;
wire            entry_exp_code_wen;
wire            entry_ready_wen;

wire            entry_vld       ,entry_vld_nxt;
wire [4:0]      entry_rd_ind    ,entry_rd_ind_nxt;
wire [31:0]     entry_val       ,entry_val_nxt;
wire            entry_branch    ,entry_branch_nxt;
wire            entry_store     ,entry_store_nxt;
wire            entry_rd_vld    ,entry_rd_vld_nxt;
wire            entry_exp_tag   ,entry_exp_tag_nxt;
wire [4:0]      entry_exp_code  ,entry_exp_code_nxt;
wire            entry_ready     ,entry_ready_nxt;
wire [5:0]  entry_inst_id   ,entry_inst_id_nxt;

// FU Val
wire            alu_rd_wen;
wire            bru_rd_wen;
wire            lsu_rd_wen;
wire            entry_flush;

wire            entry_ready_set;

wire alu_rdy_set;
wire bru_rdy_set;
wire lsu_rdy_set;

assign entry_vld_wen = rob_entry_wreq || rob_entry_ret_req || entry_flush; // Write Request pull on , and retire pull down
assign entry_vld_nxt = rob_entry_wreq && ~rob_entry_ret_req && ~entry_flush;

assign alu_rd_wen = alu_rdy_set;
assign bru_rd_wen = bru_rdy_set && bru_resp_rd_vld;
assign lsu_rd_wen = lsu_rdy_set && lsu_resp_rd_vld;

assign entry_val_wen = entry_vld && (alu_rd_wen || bru_rd_wen || lsu_rd_wen);

assign entry_val_nxt = {32{alu_rd_wen}} & alu_resp_rd_val | 
                       {32{bru_rd_wen}} & bru_resp_rd_val |  
                       {32{lsu_rd_wen}} & lsu_resp_rd_val   
                       ;

wire b_fail;

assign b_fail = bru_resp_vld && bru_flush && bru_resp_inst_id == entry_inst_id;

assign entry_branch_wen = entry_vld && (rob_entry_wreq || rob_entry_ret_req || b_fail || entry_flush);
assign entry_branch_nxt = ~rob_entry_wreq && ~rob_entry_ret_req && b_fail && ~entry_flush;

assign entry_store_wen  = rob_entry_wreq || rob_entry_ret_req ;
assign entry_store_nxt  = (rob_entry_wreq && rob_entry_wt_store) && ~rob_entry_ret_req ;

assign entry_rd_vld_wen = rob_entry_wreq || rob_entry_ret_req;
assign entry_rd_vld_nxt = rob_entry_wrd_vld && ~rob_entry_ret_req;

assign entry_rd_ind_nxt = rob_entry_wrd_ind;

assign entry_inst_id_wen = rob_entry_wreq;
assign entry_inst_id_nxt = rob_entry_winst_id;


assign alu_rdy_set = alu_resp_vld && alu_resp_inst_id == entry_inst_id;
assign bru_rdy_set = bru_resp_vld && bru_resp_inst_id == entry_inst_id;
assign lsu_rdy_set = lsu_resp_vld && lsu_resp_inst_id == entry_inst_id;

assign entry_ready_set  = alu_rdy_set || bru_rdy_set || lsu_rdy_set;
assign entry_ready_wen  = entry_vld && (rob_entry_wreq || rob_entry_ret_req || entry_ready_set || entry_flush);
assign entry_ready_nxt  = entry_vld && ~rob_entry_wreq && ~rob_entry_ret_req && entry_ready_set && ~entry_flush;

assign entry_exp_tag_wen= 1'b0;

//Flush Control
wire entry_younger;
wire entry_bru_flush;
rob_id_cmpy #(5+1) _rob_id_cmpy(entry_inst_id,bru_resp_inst_id,entry_younger);
assign entry_bru_flush = bru_flush && entry_younger;

// LSU and Exception Instruciton can cause Datapath Flush too
assign entry_flush = entry_bru_flush;

// Port Connection
assign rob_entry_ready   = entry_ready;    
assign rob_entry_vld     = entry_vld;    
assign rob_entry_inst_id = entry_inst_id;
assign rob_entry_val     = entry_val;      
assign rob_entry_bflush  = entry_branch;
assign rob_entry_eflush  = entry_exp_tag;
assign rob_entry_ecode   = entry_exp_code;
assign rob_entry_rd_vld  = entry_rd_vld;
assign rob_entry_rd_ind  = entry_rd_ind;
assign rob_entry_store   = entry_store;
//DFFs
dffr #(1)               entry_vld_ff     (clk,rst_n,entry_vld_wen     ,entry_vld_nxt     ,entry_vld      );
dffr #(32)              entry_val_ff     (clk,rst_n,entry_val_wen     ,entry_val_nxt     ,entry_val      );
dffr #(1)               entry_branch_ff  (clk,rst_n,entry_branch_wen  ,entry_branch_nxt  ,entry_branch   );
dffr #(1)               entry_store_ff   (clk,rst_n,entry_store_wen   ,entry_store_nxt   ,entry_store    );
dffr #(1)               entry_rd_vld_ff  (clk,rst_n,entry_rd_vld_wen  ,entry_rd_vld_nxt  ,entry_rd_vld   );
dffr #(5)               entry_rd_ind_ff  (clk,rst_n,rob_entry_wreq    ,entry_rd_ind_nxt  ,entry_rd_ind   );
dffr #(5+1) entry_inst_id_ff (clk,rst_n,entry_inst_id_wen ,entry_inst_id_nxt ,entry_inst_id  );
dffr #(1)               entry_exp_tag_ff (clk,rst_n,entry_exp_tag_wen ,entry_exp_tag_nxt ,entry_exp_tag  );
dffr #(5)               entry_exp_code_ff(clk,rst_n,entry_exp_code_wen,entry_exp_code_nxt,entry_exp_code );
dffr #(1)               entry_ready_ff   (clk,rst_n,entry_ready_wen   ,entry_ready_nxt   ,entry_ready    );    

endmodule

